Skip to content

Add Static Module Support#3392

Merged
ranshid merged 24 commits intovalkey-io:unstablefrom
eifrah-aws:static-lua
Apr 20, 2026
Merged

Add Static Module Support#3392
ranshid merged 24 commits intovalkey-io:unstablefrom
eifrah-aws:static-lua

Conversation

@eifrah-aws
Copy link
Copy Markdown
Contributor

@eifrah-aws eifrah-aws commented Mar 23, 2026

Add a build option to compile the Lua scripting engine as a static module and wire the server to load it directly at startup when enabled. The module load path now resolves on-load and on-unload entry points from the main binary, and the module lifecycle keeps those callbacks so unload works without a shared library handle.

The Lua module build was updated to support both static and shared variants, with the static path exporting visible wrapper symbols and linking the server with the module archive. While touching the Lua code, a few internal symbols were renamed for consistency and the monotonic time helper was clarified.

Note that this PR addresses the LUA module, but it can be applied to other "core" modules (like: Bloom, Json, Search and others). With this change, it will be easier to ship Valkey bundle with modules.

Areas touched:

  • CMake
  • Makefile
  • Lua scripting module
  • Core module loading

Generated by CodeLite

Add a build option to compile the Lua scripting engine as a static module and
wire the server to load it directly at startup when enabled. The module load
path now resolves on-load and on-unload entry points from the main binary, and
the module lifecycle keeps those callbacks so unload works without a shared
library handle.

The Lua module build was updated to support both static and shared variants,
with the static path exporting visible wrapper symbols and linking the server
with the module archive. While touching the Lua code, a few internal symbols
were renamed for consistency and the monotonic time helper was clarified.

* CMake
* Makefile
* Lua scripting module
* Core module loading

**Generated by CodeLite**

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 52.80899% with 42 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.39%. Comparing base (b2e0f63) to head (68a09c7).

Files with missing lines Patch % Lines
src/module.c 51.72% 42 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #3392      +/-   ##
============================================
- Coverage     76.45%   76.39%   -0.07%     
============================================
  Files           159      159              
  Lines         79840    79879      +39     
============================================
- Hits          61042    61022      -20     
- Misses        18798    18857      +59     
Files with missing lines Coverage Δ
src/config.c 78.09% <100.00%> (-0.24%) ⬇️
src/eval.c 91.50% <ø> (ø)
src/module.h 0.00% <ø> (ø)
src/server.c 89.60% <100.00%> (+0.10%) ⬆️
src/module.c 25.53% <51.72%> (-0.36%) ⬇️

... and 24 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ranshid ranshid added the run-extra-tests Run extra tests on this PR (Runs all tests from daily except valgrind and RESP) label Mar 23, 2026
@ranshid
Copy link
Copy Markdown
Member

ranshid commented Mar 23, 2026

No deep dive yet.

I think we need to clarify requirements before proceeding with a deep dive.

The original change aimed to:

  1. Enable users to define and use new scripting engines (e.g., LuaJIT, JavaScript)
  2. Allow users who don't use script commands (EVAL, EVALSHA) to compile and run Valkey without Lua support, avoiding frequent patching for Lua library vulnerabilities

For the 9.1 release, we must decide:

  1. Legacy Lua load/unload support: Should we support dynamically loading/unloading Lua? The current implementation allows unloading Lua (though it remains in the binary) to replace it with a different Lua module. This could enable users to dynamically "patch" Lua, but the old module persists in the code. Does this provide meaningful value?

  2. Observability: The new Lua currently appears in the module list. This may impact installations that verify module list output. This decision depends on /1 if Lua cannot be dynamically loaded/unloaded, should we list it like other modules?

@ranshid ranshid self-requested a review March 23, 2026 13:18
Comment thread src/modules/lua/script_lua.c Outdated
@madolson madolson moved this to Todo in Valkey 9.1 Mar 23, 2026
@madolson
Copy link
Copy Markdown
Member

Core team discussion:

  1. Is this is an important thing to do in 9.1?
    1. We think it's important for 9.1.
  2. We are fine with having the same observability.
  3. We are fine with unloading and not being able to reload it.
  4. If it's statically linked it's loaded automatically. If it's not statically linked it's not loaded automatically.
  5. Statically linked will the default. Review the makefile variable so that it's similar with TLS and RDMA.

@valkey-io/core-team and @rjd15372 specifically in case you have some thoughts.

See #2858 (comment) for some additional discussion.

When a scripting engine is unregistered, its cached eval scripts are now
removed as well. This prevents the eval cache from holding dangling
references to the engine after it has been unloaded.

The eval subsystem now exposes a helper for deleting all scripts owned by
a specific engine, updates the eval cache bookkeeping as entries are
removed, and logs how many scripts were cleaned up during engine
unregistration.

* scripting_engine
* eval

**Generated by CodeLite**

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
@eifrah-aws eifrah-aws marked this pull request as ready for review March 25, 2026 15:51
Update the Lua module to use the engine-provided monotonic clock helper when
built with STATIC_LUA, while keeping the module's local implementation for
non-static builds.

This avoids duplicate timing implementations and keeps elapsed-time handling
consistent across build configurations.

* Lua module
* Static build integration

**Generated by CodeLite**

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
The server startup path now only auto-loads Lua at runtime for the static
build.

Consolidate Lua scripting engine build configuration around a single BUILD_LUA
value with explicit static, module, and no modes. This removes the separate
BUILD_STATIC_LUA toggle and updates the build system to derive compile
definitions, link behavior, and module packaging from the selected mode.

* Build system
* Server startup
* Lua module packaging

**Generated by CodeLite**

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
* Build system

**Generated by CodeLite**

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
@ranshid
Copy link
Copy Markdown
Member

ranshid commented Mar 26, 2026

@eifrah-aws please check the CI failures

Adjust the module API hook test to inspect a larger tail of the replica log when verifying the shutdown event. This makes the assertion less brittle and better aligned with the amount of output produced during shutdown.

**Generated by CodeLite**

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
The extra log line caused an error to some of the TCL tests.

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
Copy link
Copy Markdown
Member

@ranshid ranshid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks very good!

One high level comment I have is the lack of good testing. Can we place some tests that verify statoc AND dynamic lua are not breaking to load/unload and that the engine can start without a lua engine (also when eval/evalsha are being generated)?

Comment thread src/modules/lua/Makefile
Comment thread src/modules/lua/Makefile
Comment thread src/modules/lua/script_lua.c Outdated
In addition, removed duplicate code.
Minor fix in the Makefile: settings LUA_MODULE_NAME to its correct name.

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
Signed-off-by: Eran Ifrah <eifrah@amazon.com>
Copy link
Copy Markdown
Contributor

@zuiderkwast zuiderkwast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good in general, but it seems the visibility attributes things are not finalized?

Comment thread src/module.c Outdated
Signed-off-by: Eran Ifrah <eifrah@amazon.com>
Update the documentation comments for the static module loading helpers to better match Valkey's standard.

* API docs

**Generated by CodeLite**

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
@zuiderkwast
Copy link
Copy Markdown
Contributor

Looks good in general, but it seems the visibility attributes things are not finalized?

@zuiderkwast can you elaborate, I am not sure I understand this comment.

I was just referring to the open comments, about symbol collisions or using __attribute__((weak)) etc. which wasn't finished last time I looked. Now they are?

- Removed __attribute__((visibility("default")))
- Added comments for the LUA_MODULE_VISIBILITY macro.

**Generated by CodeLite**

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
@eifrah-aws
Copy link
Copy Markdown
Contributor Author

I was just referring to the open comments, about symbol collisions or using
__attribute__((weak)) etc. which wasn't finished last time I looked. Now they are?

I removed un-needed code and improved comments. I also merged with latest upstream

Copy link
Copy Markdown
Member

@ranshid ranshid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

almost perfect. some small comments

Comment thread src/server.h Outdated
Comment thread src/eval.c Outdated
Comment thread src/modules/lua/engine_lua.c
Comment thread src/module.c
Comment thread src/module.c Outdated
Comment thread src/modules/lua/script_lua.c Outdated
Comment thread src/module.c Outdated
Comment thread src/module.c Outdated
The module system and Lua integration are updated to enhance reliability and stability, particularly during module loading and unloading.

Key changes include:
*   Implementing conditional compilation for Lua module entry points to support static linking gracefully.
*   Hardening module unloading logic in `module.c` by adding checks before calling `dlclose` and improving error logging if the unload function fails to load.
*   Removing the redundant `freeCachedScriptsForEngine` function in the evaluation subsystem.
*   use `__attribute__((weak))` instead of `__attribute((weak))` in `src/modules/lua/script_lua.c`.

* Module Management
* Lua Integration
* Script Evaluation

**Generated by CodeLite**

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
@eifrah-aws eifrah-aws requested a review from ranshid April 13, 2026 14:44
Signed-off-by: Eran Ifrah <eifrah@amazon.com>
Copy link
Copy Markdown
Member

@ranshid ranshid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Copy Markdown
Member

@madolson madolson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overall code looks fine to me too. Just some minor comments.

Comment thread src/module.c
Comment thread src/modules/lua/script_lua.c Outdated
Comment thread src/scripting_engine.c Outdated
Comment thread src/modules/lua/function_lua.c
Extract the common module initialization logic from `moduleLoad` and `moduleLoadStatic` into a new helper function `moduleInitPostOnLoadResolved`. This function handles the shared workflow of invoking the onload callback, registering the module, performing post-load validation, and firing server events.

The refactoring eliminates approximately 70 lines of duplicated code while preserving all existing behavior. The helper function accepts parameters that control static vs. dynamic module handling, including whether to close the dlopen handle and how to format log messages.

Both `moduleLoad` and `moduleLoadStatic` now focus on their specific responsibilities (dlopen/symbol resolution) and delegate the common initialization sequence to the shared helper.

* Module loading infrastructure
* Code deduplication

**Generated by CodeLite**

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
- Move `evalRemoveScriptsOfEngine` code to a separate PR
- Renamed `lua_scripts_flags_def` -> `lua_scripts_flags` with `static`

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
When building static lua, use:

- `getMonotonicUs()`
- `elapsedUs`
- `elapsedMs`

from the engine's `monotonic.h` header.

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
@eifrah-aws eifrah-aws requested a review from madolson April 16, 2026 14:24
Copy link
Copy Markdown
Member

@madolson madolson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay. The tests all seem unrelated, but lgtm

@eifrah-aws
Copy link
Copy Markdown
Contributor Author

Sorry for the delay. The tests all seem unrelated, but lgtm

Thanks, for the review. I have updated the branch to the latest unstable.

@ranshid ranshid merged commit 0327c27 into valkey-io:unstable Apr 20, 2026
60 of 64 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to To be backported in Valkey 9.1 Apr 20, 2026
@zuiderkwast
Copy link
Copy Markdown
Contributor

Forgot to update README.md with the build options?

sarthakaggarwal97 pushed a commit to sarthakaggarwal97/valkey that referenced this pull request Apr 23, 2026
Add a build option to compile the Lua scripting engine as a static
module and wire the server to load it directly at startup when enabled.
The module load path now resolves on-load and on-unload entry points
from the main binary, and the module lifecycle keeps those callbacks so
unload works without a shared library handle.

The Lua module build was updated to support both static and shared
variants, with the static path exporting visible wrapper symbols and
linking the server with the module archive. While touching the Lua code,
a few internal symbols were renamed for consistency and the monotonic
time helper was clarified.

Note that this PR addresses the LUA module, but it can be applied to
other "core" modules (like: Bloom, Json, Search and others). With this
change, it will be easier to ship Valkey bundle with modules.

Areas touched:

* CMake
* Makefile
* Lua scripting module
* Core module loading

**Generated by CodeLite**

---------

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-extra-tests Run extra tests on this PR (Runs all tests from daily except valgrind and RESP)

Projects

Status: To be backported

Development

Successfully merging this pull request may close these issues.

5 participants